package com.cn.serverline.lineicp.workshopPlan.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cn.serverline.lineicp.productionLine.entity.ProcessSteps;
import com.cn.serverline.lineicp.productionLine.entity.ProductMix;
import com.cn.serverline.lineicp.productionLine.entity.ProductionProcesses;
import com.cn.serverline.lineicp.productionLine.param.ProductMixTreeParam;
import com.cn.serverline.lineicp.productionLine.service.IProductMixService;
import com.cn.serverline.lineicp.productionLine.service.IProductionProcessesService;
import com.cn.serverline.lineicp.workshopPlan.consts.CommonConstant;
import com.cn.serverline.lineicp.workshopPlan.entity.Configuration;
import com.cn.serverline.lineicp.workshopPlan.entity.request.ConfigurationRequest;
import com.cn.serverline.lineicp.workshopPlan.enums.DigitEnum;
import com.cn.serverline.lineicp.workshopPlan.enums.RolingPlanException;
import com.cn.serverline.lineicp.workshopPlan.mapper.ConfigurationMapper;
import com.cn.serverline.lineicp.workshopPlan.service.ConfigurationService;
import com.serverTechnology.resource.entity.ManagementEntity;
import com.serverTechnology.resource.service.IManagementService;
import com.serverTechnology.teamsGroups.constants.FixedNames;
import com.serverTechnology.teamsGroups.entity.ProDeviceToolUser;
import com.serverTechnology.teamsGroups.entity.ProModel;
import com.serverTechnology.teamsGroups.entity.vo.ProModelVo;
import com.serverTechnology.teamsGroups.mapper.ProDeviceToolMapper;
import com.serverTechnology.teamsGroups.mapper.UserMapper;
import com.serverTechnology.teamsGroups.service.ProModelService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.stylefeng.roses.kernel.sys.modular.user.entity.SysUser;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 产线构型管理服务实现层
 */
@Service
public class ConfigurationServiceImpl extends ServiceImpl<ConfigurationMapper, Configuration> implements ConfigurationService {

    /**
     * 产品结构表
     */
    @Resource(name = "ProductMixServiceImpl")
    private IProductMixService iProductMixService;

    /**
     * 工序表
     */
    @Resource(name = "ProductionProcessesServiceImpl")
    private IProductionProcessesService iProductionProcessesService;

    @Resource
    private ProDeviceToolMapper proDeviceToolMapper;

    @Resource
    private IManagementService managementService;

    @Resource
    private UserMapper userMapper;

    @Resource
    private ProModelService proModelService;
    /**
     * 添加产线构型管理
     * @param configurationRequest 请求参数
     * @return
     */
    @Override
    public Long add(ConfigurationRequest configurationRequest) {
        Configuration spareParts = new Configuration();
        BeanUtil.copyProperties(configurationRequest, spareParts);
        spareParts.setIsDefault(CommonConstant.ZERO);
        spareParts.setCreateTime(new Date());
        this.save(spareParts);
        return spareParts.getId();
    }

    /**
     * 删除产线构型管理
     * @param configurationRequest 请求参数
     */
    @Override
    public void del(ConfigurationRequest configurationRequest) {
        this.removeById(configurationRequest.getId());
    }

    /**
     *
     * 修改产线构型管理
     * @param configurationRequest 请求参数
     */
    @Override
    public void edit(ConfigurationRequest configurationRequest) {
        // 首先，我们需要根据请求中的ID找到要修改的零组件记录
        Configuration spareParts = this.getById(configurationRequest.getId());
        // 如果记录不存在，则抛出异常或返回错误信息
        if (spareParts == null) {
            throw new ServiceException(RolingPlanException.ZERO);
        }
        // 使用BeanUtil.copyProperties方法将请求参数中的属性复制到找到的零组件记录中
        BeanUtil.copyProperties(configurationRequest, spareParts);
        // 更新修改时间
        spareParts.setUpdateTime(new Date());
        // 调用save方法来持久化更改
        this.updateById(spareParts);
    }

    /**
     * 根据传入的需要设置为默认构型的id修改成默认的其他的变成非默认的
     * @param configurationId 构型的id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDefault(Long configurationId) {
        Configuration configuration = this.getById(configurationId);
        baseMapper.updateDefault(configuration.getCtProductMixId());
        configuration.setIsDefault(CommonConstant.ONE);
        this.updateById(configuration);
    }

    /**
     * 出现问题
     * 查询详情(产线构型点击配置按钮回显)
     * @param configurationRequest 请求参数
     * @return
     */
    @Override
    public List<ConfigurationRequest> detail(ConfigurationRequest configurationRequest) {
        //查询产品结构表类别为3的数据
        LambdaQueryWrapper<ProductMix> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductMix::getCategory, DigitEnum.THREE);

        //根据类别为3的数据的id查询工序表的产品结构id
        LambdaQueryWrapper<ProductionProcesses> productionWrapper = new LambdaQueryWrapper<>();
        productionWrapper.eq(ProductionProcesses::getProductMixId,iProductMixService.getById(wrapper));

        //根据产品结构id查询工序工步表的工序id
        LambdaQueryWrapper<ProcessSteps> processStepsWrapper = new LambdaQueryWrapper<>();
        processStepsWrapper.eq(ProcessSteps::getProductionProcessesId
                ,iProductionProcessesService.getById(productionWrapper));



        //根据工序工步表的id查询工步所需非标设别，工步所需标准设备，工步所需工装，工步所需工具，工步所需图纸的name
        //根据产线数字建模查询


        // 创建 ProModelVo 列表
        List<ConfigurationRequest> proModelVoList = new ArrayList<>();

        // 查询符合条件的 ProModel 列表
        List<ProModel> list = proModelService.list(new LambdaUpdateWrapper<ProModel>()
                .eq(ProModel::getType, FixedNames.TOW)
                .eq(ProModel::getPid, configurationRequest.getPid()));

        // 提取 ProModel 的 ID 列表
        List<Long> collect = list.stream().map(ProModel::getId).collect(Collectors.toList());

        // 查询对应的 ProDeviceToolUser 列表
        List<ProDeviceToolUser> proDeviceToolUsers = proDeviceToolMapper.selectList(
                new LambdaQueryWrapper<ProDeviceToolUser>().in(ProDeviceToolUser::getPid, collect)
        );

        // 获取 ProDeviceToolUser 中的资源ID
        List<Long> resourceId = proDeviceToolUsers.stream().map(ProDeviceToolUser::getResourceId).collect(Collectors.toList());

        // 根据资源ID获取资源信息
        List<ManagementEntity> managementEntities = managementService.craftByIds(resourceId);

        // 查询用户信息
        List<SysUser> listUser = userMapper.selectList(new LambdaUpdateWrapper<SysUser>().in(SysUser::getUserId,resourceId));


        Map<Long, SysUser> userMap = listUser.stream().collect(Collectors.toMap(SysUser::getUserId, user -> user));

        // 将 ProDeviceToolUser 按 PID 分组
        Map<Long, List<ProDeviceToolUser>> proDeviceToolUserMap = proDeviceToolUsers.stream()
                .collect(Collectors.groupingBy(ProDeviceToolUser::getPid));

        // 将 ManagementEntity 转换为 Map 以便快速查找
        Map<Long, ManagementEntity> managementEntityMap = managementEntities.stream()
                .collect(Collectors.toMap(ManagementEntity::getId, entity -> entity));

        // 将 ProModel 转换为 ProModelVo 并设置子节点
        for (ProModel model : list) {
            ConfigurationRequest vo = new ConfigurationRequest();
            BeanUtil.copyProperties(model, vo); // 复制属性

            // 获取当前 ProModel 的子节点
            List<ProDeviceToolUser> children = proDeviceToolUserMap.get(model.getId());
            if (children != null) {
                // 为每个子节点设置相应的 ManagementEntity 信息
                children.forEach(child -> {
                    vo.getChildren().addAll(extracted(child.getResourceId(), managementEntityMap));
                    vo.getChildren().addAll(getList(child.getResourceId(), userMap ));
                });
            }

            proModelVoList.add(vo); // 将转换后的对象添加到列表中

        }
        return proModelVoList;

    }
    /**
     * 根据资源ID提取并生成 ProModelVo 列表
     * @param resourceId 资源ID
     * @param managementEntityMap 资源信息映射
     * @return 包含对应资源信息的 ProModelVo 列表
     */
    private List<ProModelVo> extracted(Long resourceId, Map<Long, ManagementEntity> managementEntityMap) {
        List<ProModelVo> proModelVos = new ArrayList<>();
        ManagementEntity managementEntity = managementEntityMap.get(resourceId);

        // 如果资源信息存在，则创建 ProModelVo
        if (ObjectUtil.isNotEmpty(managementEntity)) {
            ProModelVo proModelVo = new ProModelVo();
            proModelVo.setId(managementEntity.getId());
            proModelVo.setModelName(managementEntity.getResourceName());
            // 根据 deviceDistinguish 设置类型
            proModelVo.setType(managementEntity.getDeviceDistinguish().equals(FixedNames.EQUIPMENT) ? FixedNames.ZERO : FixedNames.ONE);
            proModelVo.setResourceSpecification(managementEntity.getResourceSpecification());
            proModelVos.add(proModelVo);
        }

        return proModelVos;
    }

    /**
     * 根据资源ID提取并生成 ProModelVo 列表
     * @param resourceId
     * @param userMap
     * @return
     */
    private List<ProModelVo> getList(Long resourceId, Map<Long, SysUser> userMap) {
        List<ProModelVo> proModelVos = new ArrayList<>();
        SysUser user = userMap.get(resourceId);
        if (ObjectUtil.isNotEmpty(user)){
            ProModelVo proModelVo = new ProModelVo();
            proModelVo.setId(user.getUserId());
            proModelVo.setModelName(user.getRealName());
            proModelVo.setType(FixedNames.TOW);
            proModelVos.add(proModelVo);
        }
        return proModelVos;
    }

    /**
     * 查询产线构型管理树结构
     * @param configurationRequest 产品结构树参数
     * @return
     */
    @Override
    public List<Tree<Long>> tree(ConfigurationRequest configurationRequest) {
        ProductMixTreeParam productMixTreeParam = new ProductMixTreeParam();
        productMixTreeParam.setQueryProcess(false);
        // 获取树结构
        List<Tree<Long>> tree = iProductMixService.tree(productMixTreeParam);
        List<Long> productMixIdList = new ArrayList<>();
        extracted(tree, productMixIdList);

        // 根据产品结构ID列表查询产线构型管理列表
        LambdaQueryWrapper<Configuration> wrapper = new LambdaQueryWrapper<>();
        // 根据产品结构ID列表查询产线构型管理列表
        wrapper.in(Configuration::getCtProductMixId, productMixIdList);
        // 根据产品结构ID列表查询产线构型管理列表
        List<Configuration> configurationList = this.list(wrapper);
        // 如果产线构型管理列表为空，则直接返回树结构
        if(ObjectUtil.isEmpty(configurationList)) {
            return tree;
        }
        // 根据产品结构ID列表查询产线构型管理列表
        Map<Long, List<Configuration>> listMap = configurationList.stream().collect(Collectors
                .groupingBy(Configuration::getCtProductMixId, Collectors.toList()));

        extracted(tree, listMap);
        // 返回更新后的树结构
        return tree;
    }

    private void extracted(List<Tree<Long>> tree, List<Long> productMixIdList) {
        for(Tree<Long> child : tree) {
            if(ObjectUtil.isEmpty(child.getChildren())) {
                break;
            }
            for(Tree<Long> c : child.getChildren()) {
                if(ObjectUtil.isEmpty(c.getChildren())) {
                    break;
                }
                for(Tree<Long> c1 : c.getChildren()) {
                    if(ObjectUtil.isEmpty(c1.getChildren())) {
                        break;
                    }
                    for(Tree<Long> c2 : c1.getChildren()) {
                        productMixIdList.add(c2.getId());
                    }
                }
            }
        }
    }

    private void extracted(List<Tree<Long>> tree, Map<Long, List<Configuration>> listMap) {
        for(Tree<Long> child : tree) {
            if(ObjectUtil.isEmpty(child.getChildren())) {
                break;
            }
            for(Tree<Long> c : child.getChildren()) {
                if(ObjectUtil.isEmpty(c.getChildren())) {
                    break;
                }
                for(Tree<Long> c1 : c.getChildren()) {
                    if(ObjectUtil.isEmpty(c1.getChildren())) {
                        break;
                    }
                    for (Tree<Long> c1Child : c1.getChildren()) {
                        c1Child.setChildren(TreeUtil.build(listMap.get(c1Child.getId()).stream().map(
                                configuration -> new TreeNode<>(configuration.getId(),
                                        configuration.getCtProductMixId(),configuration.getName(),configuration.getCreateTime())
                                        .setExtra(JSONUtil.parseObj(configuration))
                        ).collect(Collectors.toList()), c1Child.getId()));
                    }
                }
            }
        }
    }
}
